____在做图片的相关任务时,由于拍摄角度等原因需要对图像进行一些预处理。最近用到了仿射变换和透视变换。通过查看了别人的博客以及一些相关的书籍,整理如下:
____仿射变化主要用在对图像的形变,如旋转、平移、缩放等,它是二维空间上的变换。透视变换(Perspective Transformation)是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。一般用在图像的校正,如当摄像机与地面之间有一倾斜角的拍摄,而不是直接垂直朝下(正投影),有时希望将图象校正成正投影的形式,就需要利用透视变换。透视变换是三维空间的变换。这两种变换是通过原图像(图像矩阵)与变换矩阵的点乘来实现。
仿射变换
仿射变换矩阵是2x3的,形式如下:
其中a(11 ),a(12 ),a(21 ),a(22 )是实现线性变化(我理解为缩放因子),也可以实现旋转,只是参数不在是常数,而是旋转角度,具体可以参考https://juejin.im/post/5b0177b8f265da0ba46a128b。b1,b2 实现平移。仿射变换的方程组中有6个未知数,所以需要找到三个点组成映射,且这三个点刚好确定一个平面。
在opencv中,由cv2.getAffineTransform函数创建仿射变换矩阵,该矩阵是2x3的size,然后将该矩阵作为参数传递到cv2.warpAffine函数,实现仿射变换。Opencv还提供cv2.getRotationMatrix2D函数来实现旋转矩阵。同理将旋转矩阵作为参数传入warpAffine函数可实现图像旋转。各函数具体参数如下:
cv2.getAffineTransform(src, dst)
src: 表示输入的三个点
dst: 表示输出的三个点
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])
src - 输入图像。
M - 变换矩阵。
dsize - 输出图像的大小。
flags - 插值方法的组合(int 类型!)
borderMode - 边界像素模式(int 类型!)
borderValue - (重点!)边界填充值; 默认情况下,它为0。
上述参数中:M作为仿射变换矩阵,一般反映平移或旋转的关系,为InputArray类型的2×3的变换矩阵。
flages表示插值方式,默认为 flags=cv2.INTER_LINEAR,表示线性插值,此外还有:cv2.INTER_NEAREST(最近邻插值) cv2.INTER_AREA (区域插值) cv2.INTER_CUBIC(三次样条插值) cv2.INTER_LANCZOS4(Lanczos插值)
日常进行仿射变换时,在只设置前三个参数的情况下,如 cv2.warpAffine(img,M,(rows,cols))可以实现基本的仿射变换效果
第六个参数可以选择填充的颜色,默认为黑色
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread(r'D:\cat1.jpg')
rows,cols = img.shape[:2]
matSrc = np.float32([[50,50],[200,200],[300,100]]) #原图像上的三个点
matDst = np.float32([[100,50],[150,10],[200,100]]) #输出图像上的三个点
M = cv2.getAffineTransform(matSrc,matDst) #得到仿射变换输出矩阵
dst = cv2.warpAffine(img,M,(cols,rows))
plt.subplot(121)
plt.title('Input'),plt.imshow(img)
plt.subplot(122),plt.title('Output'),plt.imshow(dst)
plt.show()
透视变换
透视变换矩阵是3x3的:
变换矩阵可以拆成4部分,
表示线性变换,比如scaling,shearing和ratotion。
用于平移,
产生透视变换。所以可以理解成仿射等是透视变换的特殊形式。经过透视变换之后的图片通常不是平行四边形(除非映射视平面和原来平面平行的情况。所以透视变换矩阵中有8个未知数,建立透视矩阵需要在图像上找4个点和在输出图像上的对应位置,四个点中任意三个不能共线。
Opencv中用cv2. getAffineTransform函数得到透视变换矩阵,然后将该矩阵作为参数传入cv2.warpPerspectiveTransform函数实现透视变换。具体函数如下:
cv2.getPerspectiveTransform(src, dst)
src 表示输入图像的4个点
dst表示输出图像的4个点
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread(r'D:\cat1.jpg')
rows,cols = img.shape[:2]
pts1 = np.float32([[10,80],[20,180],[200,100],[100,30]])
pts2 = np.float32([[10,10],[20,100],[260,160],[300,80]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(300,200))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()